﻿// ## 2021/10/24 # 江东新风 # 将pk::add_troops换成ch::add_troops以修正显示错误 ##
// ## 2020/11/28 # messi # 搬运NAVER论坛masterpiece可向同盟势力据点支援兵力##
/*
	@제작 : masterpiecek
	@요청 : 엑시온
	@내용 : 자세력 거점에서 외교 메뉴를 사용해 타세력 거점에 병력을 지원
	在势力据点使用外交菜单支援其他势力据点
*/

/**
	[[[ 병력지원 외교 이벤트 개요 ]]]

	0. 거점의 외교메뉴 사용 - 메뉴를 실행한 거점에서 병력을 지원

	1. 기본 조건
	 1) 외교메뉴를 실행하는 건물이 거점일 것 (거점종류 유저설정 반영)
	 2) 실행거점의 태수가 존재할 것
	 3) 실행거점의 태수가 행동가능 상태일 것 - pk::is_idle(person); 함수 제대로 작동 안하는 것으로 보임
	 4) 실행군단의 행동력이 소모값 이상일 것
	 5) 실행세력의 기교P가 소모값 이상일 것
	 6) 실행거점의 병력이 최소 지원규모 이상일 것
	 7) 실행거점 주변에 적부대가 없을 것 (거점 주변 3칸 이내 - pk::enemies_around(building) 함수)

	2. 이벤트 실행여부 최초 확인 메시지
	 - 실행거점, 행동력 및 기교P 소모값 확인

	3. 타세력 거점 선택 - pk::building_selector() 함수 사용
	 1) 목표거점의 병력이 가득 차 있지 않을 것
	 2) 목표거점에 행동가능 무장이 있을 것 (태수가 있어도 행동완료 상태인 경우 제외됨)
	 3) 목표거점 주변에 적부대가 없을 것 (거점 주변 3칸 이내 - pk::enemies_around(building) 함수)
	 4) 실행거점세력과 목표거점세력이 동맹일 것 (동맹제한여부 유저설정 반영)
	 5) 실행(구역)도시에서 목표(구역)도시 간 거리가 도시거리 최대값 이내일 것 (최대거리 유저설정 반영)

	4. 병력 지원규모 결정 - pk::numberpad() 함수 사용
	 - 최소 지원규모 이상 최대 지원규모 이하의 범위에서 결정 가능

	5. 이벤트 실행여부 최종 확인 메시지
	 - 실행거점, 목표거점, 병력 지원규모 확인

	6. 출발 대사 출력 (메시지박스)
	 - 태수가 군주인 경우 반말 출력

	7. 이벤트 선처리
	 1) 행동력 소모 - district.ap 사용 (행동력의 경우 소모는 바로 되지만 표시가 딜레이가 있음
	 2) 기교P 소모 - pk::add_tp() 함수 사용

	8. 외교 화면 실행 - pk::scene(), pk::event::diplomacy() 함수 사용
	 - 무장 조형 애니메이션 - pk::anim() 함수 사용

	9. 도착 대사 출력 (메시지박스)
	 - 태수가 군주인 경우 반말 출력

	9. 이벤트 후처리
	 1) 태수 행동완료 설정 - person.action_done 사용
	 2) 실행거점 병력을 지원규모만큼 차감
	 3) 목표거점 병력을 지원규모만큼 가산
	 4) 각 거점 세력 간의 우호도 증가 (메시지박스 표시) - pk::add_relations() 함수 사용



	[[[ 추가로 고려 가능한 사항들 ]]]

	1. PK2.1의 정보저장 관련함수 버그 존재하여 시간의 흐름에 따른 이벤트 구현이 제약됨
	 : 지원거리가 늘어남에 따라 행동력, 기교P 소모값이 비례하여 증가하는 방법 고려 가능

	2. 실행거점에서 출발하는 무장을 태수가 아닌 일반무장도 가능하도록 할 것인지 여부

	3. 외교 화면에서의 대화 내용 수정여부
	 : 군주-군주, 군주-태수, 태수-군주, 태수-태수 관계를 대화에 반영할 것인지 여부 등
	 [兵力支援外交活动概要]



0. 使用据点外交菜单-在执行菜单的据点支援兵力



1. 基本条件

1）实行外交菜单的建筑物是据点（反映据点种类玩家设置）

2）执行据点的太守将存在

3）执行据点的太守可能是行动状态-pk:is idle（person）；函数似乎不正常运行

4）执行军团的行动力超过消耗值

5）执行势力的技巧P可能超过消耗值

6）执行据点的兵力至少在支援规模以上

7）执行据点周边不会有敌人部队（据点周围3格以内-pk:enemies around（building）函数）



2. 首次确认事件是否运行

-确认执行据点、行动力及技巧P消耗值



3. 选择其他势力据点-pk：building selector（）函数使用

1）目标据点的兵力不会满

2）目标据点有可行动的武装（即使有太守也被排除在行动完成状态）

3）目标据点周边不会有敌人部队（据点周围3格以内-pk:enemies around（building）函数）

4）执行据点势力和目标据点势力是同盟（反映同盟限制与否玩家设定）

5）执行（区域）城市中目标（区域）城市间距离在城市距离最大值以内（反映最大距离玩家设置）



4. 决定兵力支援规模-pk:numberpad（）函数使用

-可在最小支援规模以上最大支援规模以下的范围内决定



5. 活动运行与否最终确认信息

-确认执行据点、目标据点、兵力支援规模



6. 出发台词输出（信息框）

-太守是君主的情况下，平语输出



7. 事件预处理

1）行动力消耗-district.ap 使用（行动力的情况下，消耗是可以的，但是显示有延迟

2）技巧P消耗-pk:adtp（）函数使用



8. 外交屏幕执行-pk：scene（），pk：diplomacy（）函数使用

-武装造型动画-pk：使用anim（）函数



9. 到达台词输出（信息框）

-太守是君主的情况下，平语输出



9. 事件处理

1）太守行动完成设定-person.action_done n.使用

2）执行据点兵力支援规模的差异

3）将目标据点兵力加成支援规模

4）各据点势力之间的友好度增加（信息框显示）-pk:add relations（）函数使用





[[[[可以追加考虑的事项]]



1. 存在PK 2.1的信息存储相关函数错误，限制了随着时间的流逝而发生的活动

：支持距离增加，可考虑行动力、技巧P消耗值成比例增加的方法



2. 是否能让从执行据点出发的武装不是太守而是普通武装。



3. 是否修改外交画面中的对话内容

：君主-君主，君主-太守，太守-君主，太守-太守关系是否会反映在对话中等
*/

namespace 외교_병력지원
{

	/// ========================= 유저 설정 =========================

		/// 병력지원 기본설정
	const string 병력지원_메뉴_단축키 = "";
	const string 병력지원_메뉴_이름 = "支援兵力";
	const array<int> 병력지원_출발가능_거점형태 = { 设施_都市, 시설_관문, 시설_항구 };
	const array<int> 병력지원_도착가능_거점형태 = { 设施_都市, 시설_관문, 시설_항구 };
	const int ACTION_COST = 30;// 支援兵力所需消耗的行动力
	const int 병력지원_소모값_기교P = 100;// 支援兵力所需消耗的技巧点
	const int 병력지원_변화값_우호도 = 30;// 支援兵力所增加的友好度

	/// 병력지원 규모설정
	const int 병력지원_지원규모_최소 = 5000;// 兵力支援最小支援规模
	const int 병력지원_지원규모_최대 = 30000;// 兵力支援最大支援规模

	/// 병력을 지원할 대상거점 세력의 동맹여부 제한조건
	const bool 병력지원_지원대상_동맹한정 = true;	// 设置“true”时，只可向同盟势力据点支援兵力

	/// 병력지원 도시거리 제한조건
	// 참고 : 실행거점 또는 지원대상거점이 도시가 아닌 경우에는 해당 거점구역의 도시를 기준으로 거리판단
	const bool 병력지원_거리제한_적용 = true;// 设置“true”时，无法从执行据点支援超过一定距离的目标据点
	const int 병력지원_거리제한_거리 = 5;// 兵力支援距离限制距离

/// =============================================================

	class Main
	{

		///	<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

		pk::force@ menu_force, selected_force;
		pk::district@ menu_district;
		pk::building@ menu_base, selected_base;
		pk::person@ menu_base_taishu, selected_base_taishu;
		string menu_cost_info = "消耗行动力\x1b[1x" + ACTION_COST + "\x1b[0x,消耗技巧点\x1b[1x" + (병력지원_소모값_기교P / 2) + "\x1b[0x";
		int menu_facility_id, support_amount;
		int menu_base_taishu_id, menu_base_kunshu_id;

		///	<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

		Main()
		{
			pk::menu_item item;
			item.menu = 103;
			item.shortcut = 병력지원_메뉴_단축키;
			item.init = pk::building_menu_item_init_t(init);
			item.is_visible = pk::menu_item_is_visible_t(isVisible);
			item.is_enabled = pk::menu_item_is_enabled_t(isEnabled);
			item.get_text = cast<pk::menu_item_get_text_t@>(function() { return pk::encode(병력지원_메뉴_이름); });
			item.get_desc = pk::menu_item_get_desc_t(getDesc);
			item.handler = pk::menu_item_handler_t(handler);
			pk::add_menu_item(item);
		}

		///	<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

		void init(pk::building@ building)
		{
			@menu_force = pk::get_force(building.get_force_id());
			@menu_district = pk::get_district(building.get_district_id());
			@menu_base = @building;
			menu_facility_id = building.facility;
			menu_base_taishu_id = pk::get_taishu_id(building);
			@menu_base_taishu = pk::get_person(menu_base_taishu_id);
			menu_base_kunshu_id = pk::get_kunshu_id(menu_base);
		}

		bool isVisible()
		{
			if (menu_force.get_id() != pk::get_current_turn_force_id())
				return false;

			if (병력지원_출발가능_거점형태.find(menu_facility_id) < 0)
				return false;

			return true;
		}

		bool isEnabled()
		{
			if (!pk::is_alive(menu_base_taishu))
				return false;

			if (menu_base_taishu.action_done)
				return false;

			if (int(menu_district.ap) < ACTION_COST)
				return false;

			if (int(menu_force.tp) < 병력지원_소모값_기교P)
				return false;

			if (pk::get_troops(menu_base) < 병력지원_지원규모_최소)
				return false;

			if (pk::enemies_around(menu_base))
				return false;

			return true;
		}

		string getDesc()
		{
			if (!pk::is_alive(menu_base_taishu))
				return pk::encode("据点内无太守.(" + menu_cost_info + ")");

			if (menu_base_taishu.action_done)
				return pk::encode("据点内的太守已经完成行动.(" + menu_cost_info + ")");

			if (int(menu_district.ap) < ACTION_COST)
				return pk::encode("行动力不足.(" + menu_cost_info + ")");

			if (int(menu_force.tp) < 병력지원_소모값_기교P)
				return pk::encode("技巧点不足.(" + menu_cost_info + ")");

			if (pk::get_troops(menu_base) < 병력지원_지원규모_최소)
				return pk::encode("据点兵力不足.(" + menu_cost_info + ")");

			if (pk::enemies_around(menu_base))
				return pk::encode("据点周边存在敌军部队.(" + menu_cost_info + ")");

			return pk::encode("自势力据点支援其他势力据点.(" + menu_cost_info + ")");
		}

		bool handler()
		{
			func_병력지원_실행();

			return true;
		}

		void func_병력지원_실행()
		{
			string menu_base_name = "\x1b[1x" + pk::decode(pk::get_name(menu_base)) + "\x1b[0x";
			string choose_desc = menu_base_name + "是否向其他势力据点支援兵力?\n(" + menu_cost_info + ")";
			int choose_value = pk::choose(pk::encode(choose_desc), { pk::encode("确定"), pk::encode("取消") });
			if (choose_value == /*취소*/1) return;

			pk::list<pk::building@> selectable_base_list = get_selectable_base_list();
			if (int(selectable_base_list.count) == 0) pk::message_box(pk::encode("没有可以支援兵力的其他势力据点目标."));
			else
			{
				string selector_title = pk::encode("选择据点");
				string selector_desc = pk::encode("请选择兵力支援的其他势力据点.");
				array<pk::building@> selected_building_arr = pk::list_to_array(pk::building_selector(selector_title, selector_desc, selectable_base_list, 1, 1));
				if (int(selected_building_arr.length) > 0)
				{
					string numberpad_title = pk::encode("支援规模");
					int support_limit = pk::min(pk::get_troops(menu_base), 병력지원_지원규모_최대);
					pk::int_bool numberpad_value = pk::numberpad(numberpad_title, 병력지원_지원규모_최소, support_limit, 병력지원_지원규모_최소, pk::numberpad_t(pad_callback));
					if (numberpad_value.second)
					{
						@selected_base = selected_building_arr[0];
						//	@selected_base = pk::get_building(selected_building_arr[0].get_id());
						@selected_force = pk::get_force(selected_base.get_force_id());
						string selected_base_name = "\x1b[1x" + pk::decode(pk::get_name(selected_base)) + "\x1b[0x";
						string selected_force_name = "\x1b[2x" + pk::decode(pk::get_name(selected_force)) + "军\x1b[0x";
						support_amount = numberpad_value.first;
						string confirm_desc = menu_base_name + "是否要向" + selected_force_name + "的" + selected_base_name + "支援兵力?\n(支援规模:\x1b[1x" + support_amount + "\x1b[0x)";
						int confirm_value = pk::choose(pk::encode(confirm_desc), { pk::encode("确定"), pk::encode("取消") });
						if (confirm_value == /*결정*/0)
						{
							func_병력지원_선처리();

							string departure_msg = "向" + selected_force_name + "的" + selected_base_name + "派出兵力支援" + (menu_base_taishu_id == menu_base_kunshu_id ? "" : "确定") + ".";
							pk::message_box(pk::encode(departure_msg), menu_base_taishu);

							pk::scene(pk::scene_t(scene_병력지원_외교화면_실행));

							string arrival_msg = "派去支援" + selected_force_name + "的" + selected_base_name + "的士兵已经到达了" + (menu_base_taishu_id == menu_base_kunshu_id ? "" : "确定") + ".";
							pk::message_box(pk::encode(arrival_msg), menu_base_taishu);

							func_병력지원_후처리();

							return;
						}
					}
				}
			}

			func_병력지원_실행();
		}

		void func_병력지원_선처리()
		{
			pk::add_tp(menu_force, -병력지원_소모값_기교P, menu_base.pos);
			pk::add_ap(menu_district, -ACTION_COST);
		}

		void scene_병력지원_외교화면_실행()
		{
			pk::move_screen(selected_base.get_pos(), 1000);
			int selected_base_taishu_id = pk::get_taishu_id(selected_base);
			@selected_base_taishu = pk::get_person(selected_base_taishu_id);
			int selected_base_kunshu_id = pk::get_kunshu_id(selected_base);
			pk::person@ selected_force_gunshi = pk::get_person(selected_force.gunshi);
			pk::person@ support_person = pk::get_person(무장_문관);
			if (pk::is_alive(selected_force_gunshi) and selected_base_taishu_id == selected_base_kunshu_id) @support_person = @selected_force_gunshi;
			pk::event::diplomacy(selected_base_taishu, support_person, menu_base_taishu, pk::event::diplomacy_t(diplomacy_병력지원_외교화면_대사));
			pk::move_screen(menu_base.pos, 1000);
		}

		void diplomacy_병력지원_외교화면_대사()
		{
			string menu_base_taishu_name = "\x1b[1x" + pk::decode(pk::get_name(menu_base_taishu)) + "\x1b[0x";
			string selected_base_taishu_name = "\x1b[1x" + pk::decode(pk::get_name(selected_base_taishu)) + "\x1b[0x";
			pk::anim(0, selected_base_taishu, /*제안하는듯한*/0x37);
			pk::anim(1000, menu_base_taishu, /*준비*/0x5b);
			pk::message_box(pk::encode(menu_base_taishu_name + "大人,您找我有什么事吗?"), selected_base_taishu);
			pk::message_box(pk::encode("我是来给" + selected_base_taishu_name + "阁下支援兵力的."), menu_base_taishu);
			pk::message_box(pk::encode("刚好我军兵力不足,真是解了燃眉之急,万分感谢."), selected_base_taishu);
			pk::anim(0, selected_base_taishu, /*준비*/0x5b);
			pk::anim(1000, menu_base_taishu, /*준비*/0x5b);
			pk::message_box(pk::encode("以后也请多多关照."), menu_base_taishu);
			pk::play_se(12);
		}

		pk::list<pk::building@> get_selectable_base_list()
		{
			pk::list<pk::building@> base_list;
			for (int base_id = 0; base_id < 据点_末; base_id++)
			{
				pk::building@ base = pk::get_building(base_id);
				if (병력지원_도착가능_거점형태.find(base.facility) < 0) continue;
				if (병력지원_지원대상_동맹한정 and pk::is_enemy(menu_base, base)) continue;
				if (base.get_force_id() == menu_force.get_id()) continue;
				if (pk::get_troops(base) == pk::get_max_troops(base)) continue;
				if (int(pk::get_idle_person_list(base).count) == 0) continue;
				if (pk::enemies_around(base)) continue;

				int city_distance = get_city_distance(menu_base, base);
				if (병력지원_거리제한_적용 and city_distance > 병력지원_거리제한_거리) continue;

				base_list.add(base);
			}

			return base_list;
		}

		int get_city_distance(pk::building@ base_1, pk::building@ base_2)
		{
			int city_1_id = (base_1.get_id() < 城市_末) ? base_1.get_id() : pk::get_city_id(base_1.pos);
			int city_2_id = (base_2.get_id() < 城市_末) ? base_2.get_id() : pk::get_city_id(base_2.pos);
			return pk::get_city_distance(city_1_id, city_2_id);
		}

		string pad_callback(int line, int original_value, int current_value) { return ""; }

		void func_병력지원_후처리()
		{
			menu_base_taishu.action_done = true;
			ch::add_troops(menu_base, -support_amount, true);
			ch::add_troops(selected_base, support_amount, true);
			string menu_force_name = "\x1b[2x" + pk::decode(pk::get_name(menu_force)) + "军\x1b[0x";
			string selected_force_name = "\x1b[2x" + pk::decode(pk::get_name(selected_force)) + "军\x1b[0x";
			string relations_msg = menu_force_name + "和" + selected_force_name + "友好关系提升了";
			pk::message_box(pk::encode(relations_msg));
			//	pk::history_log(menu_base.pos, menu_force.color, pk::encode(relations_msg));
			pk::add_relations(menu_force, selected_force.get_id(), 병력지원_변화값_우호도);
		}

		///	<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

	}

	Main main;
}